package sf.tools;

import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

/**
 * 对象和map互转
 */
public class ObjectMapUtils {
    /**
     * 把JavaBean转化为map
     * @param bean
     * @return
     * @throws Exception
     */
    public static Map<String, Object> bean2map(Object bean) {
        if (bean == null) {
            return null;
        }
        Map<String, Object> map = new HashMap<>();
        //获取JavaBean的描述器
        BeanInfo b = null;
        try {
            b = Introspector.getBeanInfo(bean.getClass(), Object.class);
            //获取属性描述器
            PropertyDescriptor[] pds = b.getPropertyDescriptors();
            //对属性迭代
            for (PropertyDescriptor pd : pds) {
                //属性名称
                String propertyName = pd.getName();
                //属性值,用getter方法获取
                Method m = pd.getReadMethod();
                Object properValue = null;//用对象执行getter方法获得属性值
                properValue = m.invoke(bean);
                //把属性名-属性值 存到Map中
                map.put(propertyName, properValue);
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return map;
    }

    /**
     * 把Map转化为JavaBean
     * @param map
     * @param clz
     * @param <T>
     * @return
     * @throws Exception
     */
    public static <T> T map2bean(Map<String, Object> map, Class<T> clz) {
        if (map == null) {
            return null;
        }
        //创建一个需要转换为的类型的对象
        T obj = null;
        try {
            obj = clz.getDeclaredConstructor().newInstance();
            //从Map中获取和属性名称一样的值，把值设置给对象(setter方法)
            //得到属性的描述器
            BeanInfo b = Introspector.getBeanInfo(clz, Object.class);
            PropertyDescriptor[] pds = b.getPropertyDescriptors();
            for (PropertyDescriptor pd : pds) {
                //得到属性的setter方法
                Method setter = pd.getWriteMethod();
                //得到key名字和属性名字相同的value设置给属性
                setter.invoke(obj, map.get(pd.getName()));
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return obj;
    }

}
